package com.corpgovernment.organization.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.corpgovernment.api.organization.model.org.request.AddOrgRequest;
import com.corpgovernment.api.organization.model.org.request.DeleteRequest;
import com.corpgovernment.api.organization.model.org.response.DeleteResponse;
import com.corpgovernment.common.apollo.OrganizationApollo;
import com.corpgovernment.common.base.BaseUserInfo;
import com.corpgovernment.common.common.CorpBusinessException;
import com.corpgovernment.common.enums.ExceptionCodeEnum;
import com.corpgovernment.common.enums.PhoneCountryCodeEnum;
import com.corpgovernment.common.enums.ResourceEnum;
import com.corpgovernment.common.mq.enums.MessageBizTypeEnum;
import com.corpgovernment.common.tuple.Tuple2;
import com.corpgovernment.common.tuple.Tuple3;
import com.corpgovernment.organization.event.OrgInitEvent;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import com.ctrip.corp.obt.generic.utils.JsonUtils;

import com.corpgovernment.common.tuple.Tuple3;
import com.corpgovernment.costcenter.entity.db.MbOrgCostInfo;
import com.corpgovernment.costcenter.service.impl.CostCenterServiceImpl;
import com.corpgovernment.organization.Bo.SyncEmployeeInfoBo;
import com.corpgovernment.organization.constant.CommonConst;
import com.corpgovernment.organization.constant.OrganizationResponseCodeEnum;
import com.corpgovernment.organization.constant.SyncImportExcelConst;
import com.corpgovernment.organization.dataloader.BasicOssClientLoader;
import com.corpgovernment.organization.entity.SyncEmployeeCallBackRequestEntity;
import com.corpgovernment.organization.entity.SyncOrganizationCallBackRequestEntity;
import com.corpgovernment.organization.entity.SyncOrganizationRequestEntity;
import com.corpgovernment.organization.entity.SyncOrganizationRequestEntity.SyncOrganizationInfoEntity.PostInfoEntity;
import com.corpgovernment.organization.entity.db.*;
import com.corpgovernment.organization.enumm.*;
import com.corpgovernment.organization.event.EmployeeActionEvent;
import com.corpgovernment.organization.event.OrgInitEvent;
import com.corpgovernment.organization.mq.MultiTenantSyncEmpAndOrgProducer;
import com.corpgovernment.organization.service.*;
import com.corpgovernment.organization.util.StrUtils;
import com.corpgovernment.permission.service.RoleResourceService;
import com.corpgovernment.redis.cache.RedisUtils;
import com.corpgovernment.redis.handler.RedisHandler;
import com.ctrip.corp.obt.generic.core.context.RequestContext;
import com.ctrip.corp.obt.generic.event.core.EventCenter;
import com.ctrip.corp.obt.generic.utils.CollectionUtils;

import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import com.excel.service.excel.*;
import com.excel.util.TransactionUtils;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.BooleanUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.*;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

import static com.corpgovernment.permission.config.PermissionFilter.DATA_PERMISSION_ORG_ID_LIST;

/**
 * @author ：llw
 * @date ：Created in 2020/12/9 14:42
 * @description：
 * @modified By：
 * @version: $
 */
@Service
@Slf4j
public class SyncOrganizationServiceImpl implements ISyncOrganizationService {

    @Autowired
    private IOrganizationInfoService organizationInfoService;
    @Autowired
    private IPostService postService;
    @Autowired
    private CommonInvoiceInfoService commonInvoiceInfoService;
    @Autowired
    private ExpressAddressServiceImpl expressAddressService;
    @Autowired
    private IMbImportExcelRecordService mbImportExcelRecordService;
    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private IBdDeliveryBaseDataService bdDeliveryBaseDataService;
    @Autowired
    private OrganizationApollo organizationApollo;
    @Autowired
    private RoleResourceService roleResourceService;
    @Autowired
    @Lazy
    private EventCenter eventCenter;
    @Autowired
    private ImportOrganizationConfigService importOrganizationConfigService;
    @Autowired
    private SyncPayConfigService syncPayConfigService;
    @Autowired
    private CostCenterServiceImpl costCenterService;
    @Autowired
    private ISyncOrganizationService iSyncOrganizationService;
    @Autowired
    private BasicOssClientLoader basicOssClientLoader;
    @Autowired
    private ExcelImportProcessorFactory factory;
    @Autowired
    private TransactionUtils transactionUtils;
    @Autowired
    private RecordService recordService;
    @Autowired
    private RedisHandler redisHandler;
    @Autowired
    private MultiTenantSyncEmpAndOrgProducer multiTenantSyncEmpAndOrgProducer;
    /**
     * 新增组织
     *
     * @param org
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_UNCOMMITTED)
    public Tuple3<ServiceErrorEnum, Long, MbOrgInfo> addOrganization(SyncOrganizationRequestEntity.SyncOrganizationInfoEntity org, BaseUserInfo userInfo) {
        log.info("发送的SyncOrganizationInfoEntity：{}", JsonUtils.toJsonString(org));

        if(org.getBasicInfo().getOrgId() == null){
            org.getBasicInfo().setOrgId(UUID.randomUUID().toString());
        }

        // 组织架构参数校验
        ServiceErrorEnum checkResult = checkOrganizationRequest(org);
        String generatedOrgId = UUID.randomUUID().toString();
        org.getBasicInfo().setOrgId(generatedOrgId);
        if (checkResult != ServiceErrorEnum.Success) {
            log.info("组织架构参数校验失败：{}", JsonUtils.toJsonString(checkResult));
            return new Tuple3<>(checkResult, null, null);
        }
        MbOrgInfo parentOrgInfo = null;
        // 根据父级组织查询level
        String parentBusinessCode = org.getBasicInfo().getParentBusinessCode();
        int level = 1;
        if (StrUtil.isNotEmpty(parentBusinessCode)) {
            parentOrgInfo = organizationInfoService.findByBusinessCode(parentBusinessCode);
            if (parentOrgInfo == null) {
                throw new CorpBusinessException(OrganizationResponseCodeEnum.PARENT_ORG_IS_NULL);
            }
            level = parentOrgInfo.getLevel() + 1;
        }
        else {
            parentOrgInfo = new MbOrgInfo();
        }

        // 新增组织
        String type = org.getBasicInfo().getType();
        MbOrgInfo mbOrgInfo = new MbOrgInfo();
        mbOrgInfo.setName(org.getBasicInfo().getName());
        mbOrgInfo.setOrgType(type);
        mbOrgInfo.setParentId(parentOrgInfo.getOrgId());
        mbOrgInfo.setOrgId(generatedOrgId);
        mbOrgInfo.setLevel(level);
        mbOrgInfo.setBusinessCode(org.getBasicInfo().getBusinessCode());
        mbOrgInfo.setParentBusinessCode(org.getBasicInfo().getParentBusinessCode());
        if (org.getContactInfo() != null) {
            mbOrgInfo.setContactAreaCode(org.getContactInfo().getContactCountryCode());
            mbOrgInfo.setContactEmail(org.getContactInfo().getContactEmail());
            mbOrgInfo.setContactName(org.getContactInfo().getContactName());
            mbOrgInfo.setContactPhone(org.getContactInfo().getContactPhone());
        }
        mbOrgInfo.setValid(org.getBasicInfo().getIsActive() ? CommonConst.TRUE : CommonConst.FALSE);
        if (!organizationInfoService.createOrgInfo(mbOrgInfo)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.SAVE_ORG_FAILED);
        }
        Long newId = mbOrgInfo.getId();
        // 保存职级信息
/*        List<PostInfoEntity> postInfoList = Optional.ofNullable(org.getPostInfoList()).orElse(new ArrayList<>());
        postInfoList.forEach(postInfo -> postService.createPost(postInfo, mbOrgInfo.getOrgId()));*/


        // 先删后增 发票、配置地址信息
        saveInvoiceAndAddress(org, mbOrgInfo.getOrgId());

        // 保存成本中心
        if(StringUtils.isNotBlank(org.getBasicInfo().getCostCenterInfo())) {
            this.packageCostCenter(mbOrgInfo.getOrgId(), org.getBasicInfo().getCostCenterInfo(), org.getBasicInfo().getCostCenterInfoDefault(), type);
        }
        //非后台用户创建部门直接添加至角色下
        if (userInfo != null && !userInfo.getBgUser()) {
            roleResourceService.addOneResource(userInfo.getRoleId(), newId, mbOrgInfo.getOrgId(), type, ResourceEnum.DEPT.getCode());
        }
        return new Tuple3<>(ServiceErrorEnum.Success, newId, mbOrgInfo);
    }

    @Override
    public void sendOrgInitMsg(SyncOrganizationRequestEntity.SyncOrganizationInfoEntity org, MbOrgInfo mbOrgInfo) {

        //初始化组织设置
        OrgInitEvent orgInitEvent = new OrgInitEvent();
        OrgInitEvent.InitOrgPayType initOrgPayType = new OrgInitEvent.InitOrgPayType();
        initOrgPayType.setOrgId(mbOrgInfo.getOrgId());
        initOrgPayType.setOrgType(mbOrgInfo.getOrgType());
        orgInitEvent.setInitOrgPayType(initOrgPayType);
        orgInitEvent.setOrgConfigList(buildOrgConfigList(org.getOrgConfigEntityList()));
        orgInitEvent.setPayTypeConfigList(buildPayConfigList(org.getPayTypeConfigList()));
        log.info("初始化组织设置:{}", JsonUtils.toJsonString(orgInitEvent));
        eventCenter.post(orgInitEvent);
    }


    /**
     * 修改组织
     *
     * @param org
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class, isolation = Isolation.READ_COMMITTED)
    public Tuple3<ServiceErrorEnum, Long,MbOrgInfo> updateOrganization(SyncOrganizationRequestEntity.SyncOrganizationInfoEntity org) {
        // 组织架构参数校验
        ServiceErrorEnum checkResult = checkOrganizationRequest(org);
        if (checkResult != ServiceErrorEnum.Success) {
            return new Tuple3<>(checkResult, null, null);
        }
        String businessCode = org.getBasicInfo().getBusinessCode();
        MbOrgInfo existOrg = organizationInfoService.findByBusinessCode(businessCode);
        if(existOrg != null){
            org.getBasicInfo().setOrgId(existOrg.getOrgId());
        }
        // 修改组织
        String type = org.getBasicInfo().getType();
        MbOrgInfo mbOrgInfo = new MbOrgInfo();
        mbOrgInfo.setName(org.getBasicInfo().getName());
        mbOrgInfo.setOrgId(existOrg.getOrgId());
        mbOrgInfo.setContactAreaCode(org.getContactInfo() != null ? org.getContactInfo().getContactCountryCode() : StringUtils.EMPTY);
        mbOrgInfo.setContactEmail(org.getContactInfo() != null ? org.getContactInfo().getContactEmail() : StringUtils.EMPTY);
        mbOrgInfo.setContactName(org.getContactInfo() != null ? org.getContactInfo().getContactName() : StringUtils.EMPTY);
        mbOrgInfo.setContactPhone(org.getContactInfo() != null ? org.getContactInfo().getContactPhone() : StringUtils.EMPTY);
        mbOrgInfo.setValid(org.getBasicInfo().getIsActive() ? CommonConst.TRUE : CommonConst.FALSE);
        mbOrgInfo.setBusinessCode(org.getBasicInfo().getBusinessCode());
        mbOrgInfo.setParentId(existOrg.getParentId());
        mbOrgInfo.setOrgType(org.getBasicInfo().getType());
        mbOrgInfo.setParentBusinessCode(org.getBasicInfo().getParentBusinessCode());
        if (!organizationInfoService.updateBaseOrgInfo(mbOrgInfo)) {
            throw new CorpBusinessException(OrganizationResponseCodeEnum.UPDATE_ORG_FAILED);
        }
        // 创建职级信息
        List<PostInfoEntity> postInfoList = Optional.ofNullable(org.getPostInfoList()).orElse(new ArrayList<>());
        postInfoList.forEach(postInfo -> postService.createPost(postInfo, org.getBasicInfo().getOrgId()));
        // 先删后增 发票、配置地址信息
        saveInvoiceAndAddress(org, null);
        // 保存成本中心
        this.packageCostCenter(mbOrgInfo.getOrgId(), org.getBasicInfo().getCostCenterInfo(), org.getBasicInfo().getCostCenterInfoDefault(), type);
        return new Tuple3<>(ServiceErrorEnum.Success, existOrg.getId(), mbOrgInfo);
    }

    /**
     * 先删后增 发票、配置地址信息
     *
     * @param org
     */
    private void saveInvoiceAndAddress(SyncOrganizationRequestEntity.SyncOrganizationInfoEntity org, String orgid) {
        String orgId = StringUtils.isEmpty(orgid) ? org.getBasicInfo().getOrgId() : orgid;
        // 保存发票
        commonInvoiceInfoService.deleteByOrgId(orgId);
        if (CollectionUtils.isNotEmpty(org.getInvoiceList())) {
            List<MbCommonInvoiceInfo> mbCommonInvoiceInfoList = org.getInvoiceList().stream().map(i -> {
                MbCommonInvoiceInfo temp = new MbCommonInvoiceInfo();
                temp.setOrgId(orgId);
                temp.setInvoiceTitle(i.getInvoiceTitle());
                temp.setTaxId(i.getTaxId());
                temp.setInvoiceType(1);
                temp.setCorporationAddress(i.getCorporationAddress());
                temp.setCorporationPhone(i.getCorporationPhone());
                temp.setAccountBank(i.getAccountBank());
                temp.setAccountCardNo(i.getAccountCardNo());
                return temp;
            }).collect(Collectors.toList());
            commonInvoiceInfoService.addOrUpdateCommonInvoiceInfo(mbCommonInvoiceInfoList);
        }

        // 保存配送地址
        expressAddressService.deleteByOrgId(orgId);

        if (CollectionUtils.isNotEmpty(org.getDeliveryAddressList())) {
       /*     List<String> names = new ArrayList<>();
            for (SyncOrganizationRequestEntity.SyncOrganizationInfoEntity.DeliveryAddressEntity addressEntity : org.getDeliveryAddressList()) {
                names.add(addressEntity.getCityName());
                names.add(addressEntity.getDistrictName());
                names.add(addressEntity.getProvinceName());
            }
            List<BdDeliveryBaseData> bdDeliveryBaseData = bdDeliveryBaseDataService.queryByNames(names.stream().filter(Objects::nonNull).distinct().collect(Collectors.toList()));
            Map<String, String> dataMap = bdDeliveryBaseData.stream().collect(Collectors.toMap(x -> x.getName() + x.getType(), BdDeliveryBaseData::getCode, (k1, k2) -> k1));*/
            List<MbExpressAddress> mbExpressAddressList = org.getDeliveryAddressList().stream().map(a -> {

                MbExpressAddress temp = new MbExpressAddress();
                temp.setOrgId(orgId);
                temp.setProvince(a.getProvinceCode());
                temp.setProvinceName(a.getProvinceName());
                temp.setCity(a.getCityCode());
                temp.setCityName(a.getCityName());
                temp.setDistrict(a.getDistrictCode());
                temp.setDistrictName(a.getDistrictName());
                temp.setAddress(a.getAddress());
                temp.setRecipientName(a.getRecipientName());
                temp.setCountryCode(a.getRecipientCountryCode());
                temp.setRecipientPhone(a.getRecipientPhone());
                temp.setPostCode(a.getPostCode());
                temp.setIsDefault(a.getIsDefault());
                temp.setIsCorporation(false);
                return temp;
            }).collect(Collectors.toList());
            expressAddressService.insertBatch(mbExpressAddressList);
        } else {
            if (OrgTypeEnum.D.getCode().equals(org.getBasicInfo().getType())){
                //查询部门所属公司
                MbOrgInfo corpOrgInfo = organizationInfoService.findRecentCompanyIdByOrgId(orgId);
                List<MbExpressAddress> listByOrgIds = expressAddressService.findListByOrgIds(Lists.newArrayList(corpOrgInfo.getOrgId()));
                if (CollectionUtils.isNotEmpty(listByOrgIds) && listByOrgIds.size() > 0){
                    listByOrgIds.forEach(item ->{
                        item.setId(null);
                        item.setOrgId(orgId);
                    });
                    expressAddressService.insertBatch(listByOrgIds);
                }
            }
        }
    }

    /**
     * 删除组织
     *
     * @param org
     * @return
     */
    @Override
    public Tuple3<ServiceErrorEnum, Long,MbOrgInfo> deleteOrganization(SyncOrganizationRequestEntity.SyncOrganizationInfoEntity org, BaseUserInfo userInfo) {

        // 组织架构参数校验
        if (org == null || org.getBasicInfo() == null || org.getBasicInfo().getBusinessCode() == null) {
            ServiceErrorEnum serviceErrorEnum = ServiceErrorEnum.SyncHumanResources_NewError;
            serviceErrorEnum.setErrorMessage(ImportExcelRecordDetailLogErrorMessageEnum.H.getErrorMessage());
            return new Tuple3<>(serviceErrorEnum, null,null);
        }
        List<MbOrgInfo> mbOrgInfoList = organizationInfoService.listByBusinessCode(Collections.singletonList(org.getBasicInfo().getBusinessCode()));
        if (CollectionUtils.isEmpty(mbOrgInfoList)){
            return new Tuple3<>(ServiceErrorEnum.SyncHumanResources_SyncOrgInfo_Business_Code_Is_Empty, null,null);
        }
        // 删除组织，逻辑同页面点击删除
        DeleteRequest deleteRequest = new DeleteRequest();
        deleteRequest.setOrgId(mbOrgInfoList.get(0).getOrgId());
        DeleteResponse deleteResponse = organizationInfoService.delete(deleteRequest, userInfo);
        if (deleteResponse != null && deleteResponse.getCode() != null && deleteResponse.getCode().equals(0)) {
            return new Tuple3<>(ServiceErrorEnum.Success, deleteResponse.getOrgId(),null);
        }
        ServiceErrorEnum serviceErrorEnum = ServiceErrorEnum.SyncHumanResources_NewError;
        serviceErrorEnum.setErrorMessage(deleteResponse.getMessage());
        return new Tuple3<>(serviceErrorEnum, null,null);
    }

    /**
     * 检测组织参数
     *
     * @param org
     * @return
     */
    private ServiceErrorEnum checkOrganizationRequest(SyncOrganizationRequestEntity.SyncOrganizationInfoEntity org) {
        // 空值判断
        if (org == null) {
            log.error("checkOrganizationRequest org 空值判断");
            return ServiceErrorEnum.SyncHumanResources_SyncOrgInfo_EmptyOrgInfo_Failure;
        }
        // 默认不删除
        org.setIsDelete(Optional.ofNullable(org.getIsDelete()).orElse(false));

        // 空值判断
        if (org.getBasicInfo() == null
                || StringUtils.isEmpty(org.getBasicInfo().getName())
                || StringUtils.isEmpty(org.getBasicInfo().getType())) {
            log.error("checkOrganizationRequest org.getBasicInfo() 空值判断");
            return ServiceErrorEnum.SyncHumanResources_SyncOrgInfo_EmptyBasicInfo_Failure;
        }
        // 超出赋值范围
        if (!In(org.getBasicInfo().getType(), OrgTypeEnum.C.getCode(), OrgTypeEnum.D.getCode())) {
            log.error("checkOrganizationRequest org.getBasicInfo().getType()为{} 超出赋值范围C或D", org.getBasicInfo().getType());
            return ServiceErrorEnum.SyncHumanResources_SyncOrgInfo_OutOfOrgType_Failure;
        }
        // 顶层组织，只能是公司
        if (OrgTypeEnum.D.getCode().equals(org.getBasicInfo().getType()) && StringUtils.isEmpty(org.getBasicInfo().getParentBusinessCode())) {
            log.error("checkOrganizationRequest 顶层组织，只能是公司");
            return ServiceErrorEnum.SyncHumanResources_SyncOrgInfo_ErrorParentOrgId_Failure;
        }
        // 默认有效
        org.getBasicInfo().setIsActive(Optional.ofNullable(org.getBasicInfo().getIsActive()).orElse(true));


        // 联系人信息判断
        if (org.getContactInfo() != null) {
            PhoneCountryCodeEnum phoneCountryCodeEnum = StringUtils.isEmpty(org.getContactInfo().getContactCountryCode()) ? PhoneCountryCodeEnum.CN : PhoneCountryCodeEnum.getByCountryCode(org.getContactInfo().getContactCountryCode());
            if (phoneCountryCodeEnum == null) {
                return  ServiceErrorEnum.SyncHumanResources_SyncOrgInfo_ContactInfo_CountryCodeFormat_Failure;
            }
            if (!StringUtils.isEmpty(org.getContactInfo().getContactEmail()) && !org.getContactInfo().getContactEmail().matches("^[A-Za-z0-9\\-_]+[A-Za-z0-9\\.\\-_]*[A-Za-z0-9\\-_]+@[A-Za-z0-9]+[A-Za-z0-9\\.\\-_]*(\\.[A-Za-z0-9\\.\\-_]+)*[A-Za-z0-9]+\\.[A-Za-z0-9]+[A-Za-z0-9\\.\\-_]*[A-Za-z0-9]+$")) {
                return ServiceErrorEnum.SyncHumanResources_SyncOrgInfo_ContactInfo_EmailFormat_Failure;

            }
            Pattern p = Pattern.compile("^1[3-9]\\d{9}$");
            if (!StringUtils.isEmpty(org.getContactInfo().getContactPhone()) && !p.matcher(org.getContactInfo().getContactPhone()).find()) {
                return ServiceErrorEnum.SyncHumanResources_SyncOrgInfo_ContactInfo_PhoneFormat_Failure;
            }
        }

        if (CollectionUtils.isNotEmpty(org.getInvoiceList())) {
            // 只有公司才能关联发票
            if (!OrgTypeEnum.C.getCode().equals(org.getBasicInfo().getType())) {
                log.error("checkOrganizationRequest 只有公司才能关联发票，删除发票");
                return ServiceErrorEnum.SyncHumanResources_SyncOrgInfo_InvoiceButNotCompany_Failure;
            }

            for (SyncOrganizationRequestEntity.SyncOrganizationInfoEntity.InvoiceInfoEntity invoice : org.getInvoiceList()) {
                // 空值判断
                if (invoice != null && (StringUtils.isEmpty(invoice.getInvoiceTitle()) || StringUtils.isEmpty(invoice.getTaxId())
                        || StringUtils.isEmpty(invoice.getAccountBank()) || StringUtils.isEmpty(invoice.getAccountCardNo())
                        || StringUtils.isEmpty(invoice.getCorporationPhone()) || StringUtils.isEmpty(invoice.getCorporationAddress()))) {
                    log.error("checkOrganizationRequest org.getInvoiceTitle() 空值判断");
                    return ServiceErrorEnum.SyncHumanResources_SyncOrgInfo_EmptyInvoiceInfo_Failure;
                }
            }
            // 去除null项
            org.getInvoiceList().removeIf(Objects::isNull);
        }

        if (CollectionUtils.isNotEmpty(org.getDeliveryAddressList())) {
            for (SyncOrganizationRequestEntity.SyncOrganizationInfoEntity.DeliveryAddressEntity address : org.getDeliveryAddressList()) {
                // 空值判断
                if (address != null && (StringUtils.isEmpty(address.getProvinceName()) || StringUtils.isEmpty(address.getCityName())
                        || StringUtils.isEmpty(address.getDistrictName()) || StringUtils.isEmpty(address.getAddress())
                        || StringUtils.isEmpty(address.getRecipientName()) || StringUtils.isEmpty(address.getRecipientPhone()))) {
                    log.error("checkOrganizationRequest org.getDeliveryAddressList() 空值判断");
                    return ServiceErrorEnum.SyncHumanResources_SyncOrgInfo_EmptyDeliveryInfo_Failure;
                }
                if (address != null) {
                    // 默认不是默认配送地址
                    address.setIsDefault(Optional.ofNullable(address.getIsDefault()).orElse(false));
                    PhoneCountryCodeEnum phoneCountryCodeEnum = StringUtils.isEmpty(address.getRecipientCountryCode()) ? null : PhoneCountryCodeEnum.getByCountryCode(address.getRecipientCountryCode());
                    if (phoneCountryCodeEnum == null) {
                        // 默认中国大陆
                        address.setRecipientCountryCode(PhoneCountryCodeEnum.CN.getCountryCode());
                    }
                    if (!StringUtils.isEmpty(address.getPostCode()) && !address.getPostCode().matches("^[0-9]\\d{5}$")) {
                        return ServiceErrorEnum.SyncHumanResources_SyncOrgInfo_DeliveryAddress_PostCodeFormat_Failure;
                    }
                    Pattern p = Pattern.compile("^1[3-9]\\d{9}$");
                    if (!StringUtils.isEmpty(address.getRecipientPhone()) && !p.matcher(address.getRecipientPhone()).find()) {
                        return ServiceErrorEnum.SyncHumanResources_SyncOrgInfo_DeliveryAddress_PhoneFormat_Failure;
                    }
                }
            }
            // 去除null项
            org.getDeliveryAddressList().removeIf(Objects::isNull);
        }


        if (CollectionUtils.isNotEmpty(org.getPostInfoList())) {
            for (PostInfoEntity postInfoEntity : org.getPostInfoList()) {
                if (StringUtils.isBlank(postInfoEntity.getName())) {
                    return ServiceErrorEnum.SyncHumanResources_SyncEmployeeInfo_PostInfo_Failure;
                }
            }
        }

        return ServiceErrorEnum.Success;
    }

    @Override
    public void insertRecordDetailLog(SyncOrganizationRequestEntity.SyncOrganizationInfoEntity org, String errorMessage) {
        MbImportExcelRecordDetailLog mbImportExcelRecordDetailLog = new MbImportExcelRecordDetailLog();
        mbImportExcelRecordDetailLog.setRecordId(org.getRecordId());
        mbImportExcelRecordDetailLog.setMessage(errorMessage);
        mbImportExcelRecordDetailLog.setStatus("F");
        mbImportExcelRecordDetailLog.setLineNo(org.getLineNo());
        mbImportExcelRecordDetailLog.setSheetIndex(OrgInfoSheetEnum.INFO.getIndex());
        mbImportExcelRecordDetailLog.setSheetName(OrgInfoSheetEnum.INFO.getName());
        mbImportExcelRecordDetailLog.setMainLineNo(org.getLineNo());
        try {
            mbImportExcelRecordService.insertRecordDetailLog(mbImportExcelRecordDetailLog);
        } catch (Exception e) {
            log.error("addOrganization insert recordDetailLog error", e);
        }
    }

    @Override
    public void syncOrgInfo(SyncOrganizationRequestEntity entity, String tags) throws Exception {
        SyncOrganizationCallBackRequestEntity callback = new SyncOrganizationCallBackRequestEntity();
        BaseUserInfo userInfo = new BaseUserInfo();
        BeanUtils.copyProperties(entity, userInfo);
        for (SyncOrganizationRequestEntity.SyncOrganizationInfoEntity org : entity.getOrgInfoList()) {
            Tuple3<ServiceErrorEnum, Long, MbOrgInfo> resultTuple = null;
            try {
                // 根据不同Tag消费同步消息
                if (MessageBizTypeEnum.SYNC_ORGANIZATION_ADD.getTags().equals(tags)) {
                    callback.setType(SyncOrganizationCallBackRequestEntity.SYNC_ORGANIZATION_OPERATION_TYPE_ADD);
                    log.info("addOrganization，result：{}", resultTuple = iSyncOrganizationService.addOrganization(org, userInfo));
                    if (resultTuple != null && resultTuple.getThird() != null){
                        org.setMbOrgInfo(resultTuple.getThird());
                        //iSyncOrganizationService.sendOrgInitMsg(org, resultTuple.getThird());
                    }
                } else if (MessageBizTypeEnum.SYNC_ORGANIZATION_UPDATE.getTags().equals(tags)) {
                    callback.setType(SyncOrganizationCallBackRequestEntity.SYNC_ORGANIZATION_OPERATION_TYPE_UPDATE);
                    log.info("updateOrganization，result：{}", resultTuple = iSyncOrganizationService.updateOrganization(org));
                    if (resultTuple != null && resultTuple.getThird() != null){
                        org.setMbOrgInfo(resultTuple.getThird());
                        //iSyncOrganizationService.sendOrgInitMsg(org, resultTuple.getThird());
                    }
                } else if (MessageBizTypeEnum.SYNC_ORGANIZATION_DELETE.getTags().equals(tags)) {
                    callback.setType(SyncOrganizationCallBackRequestEntity.SYNC_ORGANIZATION_OPERATION_TYPE_DELETE);
                    log.info("deleteOrganization，result：{}", resultTuple = iSyncOrganizationService.deleteOrganization(org, userInfo));
                }
                if (resultTuple != null && ServiceErrorEnum.Success.getErrorCode().equals(resultTuple.getFirst().getErrorCode())) {
                    redisUtils.increment(SyncImportExcelConst.IMPORT_SUCCESS + org.getRecordId());
                } else {
                    this.insertRecordDetailLog(org, resultTuple == null ? "resultTuple is null" : resultTuple.getFirst().getErrorMessage());
                }
            } catch (Exception ex) {
                log.error("SyncOrganizationMsgConsumer", ex);
                this.insertRecordDetailLog(org, ex.getMessage());
                throw ex;
            } finally {
                redisUtils.increment(SyncImportExcelConst.CONSUME_NUM + org.getRecordId());
                int importedNumber = redisUtils.getCache(SyncImportExcelConst.CONSUME_NUM + org.getRecordId(), Integer.class);
                int total = redisUtils.getCache(SyncImportExcelConst.IMPORT_TOTAL + org.getRecordId(), Integer.class);
                if (importedNumber == total) {
                    Integer successObj = redisUtils.getCache(SyncImportExcelConst.IMPORT_SUCCESS + org.getRecordId(),  Integer.class);
                    int success = successObj == null ? 0 : (int) successObj;
                    MbImportExcelRecord mbImportExcelRecord = new MbImportExcelRecord();
                    mbImportExcelRecord.setId(org.getRecordId());
                   /* MbImportExcelRecord record = mbImportExcelRecordService.getRecordById(org.getRecordId());
                    mbImportExcelRecord.setFailCount(record.getTotalCount() - success);
                    if (success > 0) {
                        mbImportExcelRecord.setStatus(MbImportExcelRecordStatusEnum.E.getDealCode());
                    } else {
                        mbImportExcelRecord.setStatus(MbImportExcelRecordStatusEnum.F.getDealCode());
                    }*/
                    //更新数据删除key
                    mbImportExcelRecordService.updateRecord(mbImportExcelRecord);
                    redisUtils.delete(SyncImportExcelConst.CONSUME_NUM + org.getRecordId());
                    redisUtils.delete(SyncImportExcelConst.IMPORT_TOTAL + org.getRecordId());
                    redisUtils.delete(SyncImportExcelConst.IMPORT_SUCCESS + org.getRecordId());
                }
            }
        }
    }

    @Override
    public <PREINSERT> void handleEmployImport(MultipartFile file, BaseUserInfo baseUserInfo, String syncTpye,String defaultBusinessCode){

        List<SyncEmployeeCallBackRequestEntity.FailInfo> errorList = new ArrayList<>();

        List<SyncOrganizationRequestEntity.SyncOrganizationInfoEntity> dataList = new ArrayList<>();

        // 上传excel资源到阿里云
        String fileUrl = basicOssClientLoader.putPrivateObject(file);

        //向操作记录标插入数据
        MbImportExcelRecord record = recordService.insertOrgRecord(baseUserInfo, file.getOriginalFilename(), fileUrl, 0);

        try {
            BizImportTaskImpl<MbImportExcelRecord,Object> task = new BizImportTaskImpl<>();
            task.setBasic(record);
            task.setExt(defaultBusinessCode);

            ExcelImportProcessor processor = factory.getMessageHandler("org_"+syncTpye+"_v1");
            if (processor != null) {

                BizImportResult<SyncEmployeeCallBackRequestEntity.FailInfo, SyncOrganizationRequestEntity.SyncOrganizationInfoEntity> excelDataRes = processor.assembleListFromExcel(task,file);

                dataList = excelDataRes.getData();

                if(CollectionUtils.isEmpty(dataList)){
                    // 记录错误日志 并更新记录状态
                    throw new CorpBusinessException(OrganizationResponseCodeEnum.FILE_IS_NULL);
                }

                BizImportResult<SyncEmployeeCallBackRequestEntity.FailInfo, SyncOrganizationRequestEntity.SyncOrganizationInfoEntity> checkExcelDataRes =  processor.checkExcelData(dataList);

                BizImportPreInsertResult<SyncEmployeeCallBackRequestEntity.FailInfo, SyncOrganizationRequestEntity.SyncOrganizationInfoEntity, PREINSERT> checkDbDataRes =  processor.checkDbDataWithPreInsert(dataList);

                BizImportResult<SyncEmployeeCallBackRequestEntity.FailInfo, SyncOrganizationRequestEntity.SyncOrganizationInfoEntity> checkDataPermissionRes =  processor.checkDataPermission(dataList);


                if(excelDataRes != null) {
                    errorList.addAll(excelDataRes.getError());
                }
                if(checkExcelDataRes != null) {
                    errorList.addAll(checkExcelDataRes.getError());
                }
                if(checkDbDataRes != null) {
                    errorList.addAll(checkDbDataRes.getError());
                }
                if(checkDataPermissionRes != null) {
                    errorList.addAll(checkDataPermissionRes.getError());
                }

                if(CollectionUtil.isNotEmpty(errorList)){
                    // 有报错且全量回滚
                    // 记录错误日志 并更新记录状态
                    recordService.recordProblems(baseUserInfo, errorList, dataList.size(), record.getId());
                    throw new CorpBusinessException(OrganizationResponseCodeEnum.IMPORT_ORG_EXCEL_ERROR);
                }

                redisHandler.setValue(SyncImportExcelConst.IMPORT_TOTAL + record.getId(), dataList.size(), 60 * 20);

                // 最后开启整体事务插入，防止脏数据写入后未删除
                List<SyncOrganizationRequestEntity.SyncOrganizationInfoEntity> finalDataList = dataList;
                transactionUtils.runInTransaction(() -> {

                    for (SyncOrganizationRequestEntity.SyncOrganizationInfoEntity o : finalDataList) {
                        if(SyncEmployeeInfoBo.SyncType.ADD.getDesc().equals(syncTpye)){
                            if (BooleanUtils.isTrue(o.getIsDelete())) {
                                multiTenantSyncEmpAndOrgProducer.sendSyncOrgMsgV1(o, null, MessageBizTypeEnum.SYNC_ORGANIZATION_DELETE, baseUserInfo);
                                continue;
                            }
                            multiTenantSyncEmpAndOrgProducer.sendSyncOrgMsgV1(o, null, MessageBizTypeEnum.SYNC_ORGANIZATION_ADD, baseUserInfo);
                        }
                        // 修改
                        if(SyncEmployeeInfoBo.SyncType.UPDATE.getDesc().equals(syncTpye)){
                            if (BooleanUtils.isTrue(o.getIsDelete())) {
                                multiTenantSyncEmpAndOrgProducer.sendSyncOrgMsgV1(o, null, MessageBizTypeEnum.SYNC_ORGANIZATION_DELETE, baseUserInfo);
                                continue;
                            }

                            multiTenantSyncEmpAndOrgProducer.sendSyncOrgMsgV1(o, null, MessageBizTypeEnum.SYNC_ORGANIZATION_UPDATE, baseUserInfo);
                        }
                    }

                });

                for (SyncOrganizationRequestEntity.SyncOrganizationInfoEntity o : finalDataList) {
                    if(ObjectUtil.isNotNull(o.getMbOrgInfo())){
                        iSyncOrganizationService.sendOrgInitMsg(o, o.getMbOrgInfo());
                    }
                }

                // 记录错误日志 并更新记录状态
                recordService.recordProblems(baseUserInfo, errorList, dataList.size(), record.getId());

            }
        }catch (CorpBusinessException e){
            // 记录错误日志 并更新记录状态
            if(CollectionUtils.isEmpty(errorList)){
                SyncEmployeeCallBackRequestEntity.FailInfo errorLog = new SyncEmployeeCallBackRequestEntity.FailInfo();
                errorLog.setMainLineNo("");
                errorLog.setLineNo("");
                errorLog.setSheetName(SyncEmployeeInfoBo.SheetEnum.EMP.getName());
                errorLog.setSheetIndex(SyncEmployeeInfoBo.SheetEnum.EMP.getIndex());
                errorLog.setFailReason(e.getMessage());
                errorList.add(errorLog);
                recordService.recordProblems(baseUserInfo, errorList, dataList.size(), record.getId());
            }
            throw e;
        }catch (Exception e){
            // 记录错误日志 并更新记录状态
            if(CollectionUtils.isEmpty(errorList)){
                SyncEmployeeCallBackRequestEntity.FailInfo errorLog = new SyncEmployeeCallBackRequestEntity.FailInfo();
                errorLog.setMainLineNo("");
                errorLog.setLineNo("");
                errorLog.setSheetName(SyncEmployeeInfoBo.SheetEnum.EMP.getName());
                errorLog.setSheetIndex(SyncEmployeeInfoBo.SheetEnum.EMP.getIndex());
                errorLog.setFailReason(e.getMessage());
                errorList.add(errorLog);
                recordService.recordProblems(baseUserInfo, errorList, dataList.size(), record.getId());
            }
            throw e;
        }

    }


    /**
     * 成本中心处理
     * @param orgId 组织ID
     * @param costCenterInfo 成本中心字符串 数据示例： 成本中心编码/成本中心名称;成本中心编码2/成本中心名称2
     */
    private void packageCostCenter(String orgId, String costCenterInfo, String costCenterInfoDefault, String type) {
        log.info("机构导入机构id：{}，成本中心：{}，默认成本中心：{}，类型{}", orgId, costCenterInfo, costCenterInfoDefault, type);
        if (StringUtils.isBlank(costCenterInfo)) {
            return;
        }
        MbOrgInfo companyOrgInfo = organizationInfoService.findRecentCompanyIdByOrgId(orgId);
        Map<String, MbOrgCostInfo> costCenterCodeMap =
            costCenterService.costCenterCodeMapByCompany(companyOrgInfo.getOrgId());
        String[] costCenters = costCenterInfo.split(";");
        List<AddOrgRequest.CostCenterInfo> costCenterInfoList = new ArrayList<>(costCenters.length);
        Map<String, String> costCenterMap = new HashMap<>(costCenters.length);
        for (String costCenter : costCenters) {
            if (!costCenter.contains("/")) {
                throw new CorpBusinessException(OrganizationResponseCodeEnum.COST_CENTER_FORMAT_ERROR);
            }
            String[] content = costCenter.split("/");
            if (content.length != 2) {
                throw new CorpBusinessException(OrganizationResponseCodeEnum.COST_CENTER_FORMAT_ERROR);
            }
            if(costCenterMap.containsKey(content[1])) {
                throw new CorpBusinessException(OrganizationResponseCodeEnum.COST_CENTER_FORMAT_REPEAT);
            } else {
                costCenterMap.put(content[1], content[0]);
            }

            MbOrgCostInfo mbOrgCostInfo = costCenterCodeMap.get(content[1]);
            if(OrgTypeEnum.D.getCode().equals(type)) {

                // 部门才校验成本中心必须存在
                if (null == mbOrgCostInfo) {
                    throw new CorpBusinessException(OrganizationResponseCodeEnum.COST_CENTER_DONT_BELONG_COMPANY_ERROR, content[1]);
                }

                if (!mbOrgCostInfo.getCostCenterName().equals(content[0])) {
                    throw new CorpBusinessException(OrganizationResponseCodeEnum.COST_CENTER_NAME_ERROR);
                }
            } else if(mbOrgCostInfo != null) {
                if (!mbOrgCostInfo.getCostCenterName().equals(content[0])) {
                    throw new CorpBusinessException(OrganizationResponseCodeEnum.COST_CENTER_NAME_ERROR);
                }
            }

            AddOrgRequest.CostCenterInfo addCostCenterInfo = new AddOrgRequest.CostCenterInfo();
            addCostCenterInfo.setCostCenterCode(content[1]);
            addCostCenterInfo.setCostCenterName(content[0]);
            costCenterInfoList.add(addCostCenterInfo);
        }
        if (CollectionUtils.isNotEmpty(costCenterInfoList)) {
            costCenterService.saveCostCenterInfoByOrg(orgId, costCenterInfoList);
        }

        if(StringUtils.isNotBlank(costCenterInfoDefault)) {
            // 默认成本中心
            AddOrgRequest.CostCenterInfo addCostCenterInfo = new AddOrgRequest.CostCenterInfo();
            String[] contentDefault = costCenterInfoDefault.split("/");
            if (contentDefault.length != 2) {
                throw new CorpBusinessException(OrganizationResponseCodeEnum.COST_CENTER_DEFAULT_FORMAT_ERROR);
            }
            addCostCenterInfo.setCostCenterCode(contentDefault[1]);
            addCostCenterInfo.setCostCenterName(contentDefault[0]);
            costCenterService.saveOrgCostDefaultDepartmentByOrg(orgId, addCostCenterInfo);
        }



    }

    private List<OrgInitEvent.OrgConfigType> buildOrgConfigList(List<SyncOrganizationRequestEntity.SyncOrganizationInfoEntity.OrgConfigEntity> orgConfigEntity){
        if (CollectionUtils.isEmpty(orgConfigEntity)){
           return Collections.emptyList();
        }
        return orgConfigEntity.stream().map(entity->{
            OrgInitEvent.OrgConfigType orgConfigType = new OrgInitEvent.OrgConfigType();
            orgConfigType.setType(entity.getType());
            orgConfigType.setBusinessCode(entity.getBusinessCode());
            orgConfigType.setProjectIsNeed(entity.getProjectIsNeed());
            orgConfigType.setCostCenterIsNeed(entity.getCostCenterIsNeed());
            return orgConfigType;
        }).collect(Collectors.toList());

    }
    private List<OrgInitEvent.PayTypeConfigType> buildPayConfigList(List<SyncOrganizationRequestEntity.SyncOrganizationInfoEntity.PayTypeConfigEntity> payTypeConfigEntityList){
        if (CollectionUtils.isEmpty(payTypeConfigEntityList)){
            return Collections.emptyList();
        }
        return payTypeConfigEntityList.stream().map(entity->{
            OrgInitEvent.PayTypeConfigType payTypeConfigType = new OrgInitEvent.PayTypeConfigType();
            payTypeConfigType.setBusinessCode(entity.getBusinessCode());
            payTypeConfigType.setOrgId(entity.getOrgId());
            payTypeConfigType.setCar(entity.getCarPub());
            payTypeConfigType.setHotel(entity.getHotelPub());
            payTypeConfigType.setFlight(entity.getFlightPub());
            payTypeConfigType.setHotelintl(entity.getHotelintlPub());
            payTypeConfigType.setFlightintl(entity.getFlightintlPub());
            payTypeConfigType.setTrain(entity.getTrainPub());
            return payTypeConfigType;
        }).collect(Collectors.toList());

    }
    private static boolean In(String source, String... params) {
        if (params != null && params.length > 0) {
            String[] var2 = params;
            int var3 = params.length;

            for(int var4 = 0; var4 < var3; ++var4) {
                String s = var2[var4];
                if (StringUtils.equalsIgnoreCase(s, source)) {
                    return true;
                }
            }

            return false;
        } else {
            return false;
        }
    }

}
